package com.iwunu.auth.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.iwunu.auth.config.JwtConfig;
import com.iwunu.auth.util.JwtTokenUtil;
import com.iwunu.auth.vo.JwtUserVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt登录过滤器
 *
 * @author vivi207
 */
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(JWTLoginFilter.class);

    private AuthenticationManager authenticationManager;

    private JwtTokenUtil jwtTokenUtil;

    public JWTLoginFilter(AuthenticationManager authenticationManager, JwtTokenUtil jwtTokenUtil) {
        this.authenticationManager = authenticationManager;
        this.jwtTokenUtil = jwtTokenUtil;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException {
        try {
            LOGGER.debug("解析用户信息，放入凭证...");
            //JwtUserVo user = new ObjectMapper().readValue(req.getInputStream(), JwtUserVo.class);
            JwtUserVo user = new JwtUserVo();
            user.setUsername(req.getParameter("username").toString());
            user.setPassword(req.getParameter("password").toString());

            res.addHeader("ID",user.getUsername());

            LOGGER.debug("用户登录信息:{}", user);
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities()));
        } catch (Exception e) {
            LOGGER.error("密码错误");
            res.setCharacterEncoding("UTF-8");
            res.setContentType("application/json; charset=utf-8");
            res.setStatus(401);
            PrintWriter printWriter = null;
            String resultJson = null;
            try {
                printWriter = res.getWriter();
                Map<String, Object> result = new HashMap<>();
                result.put("code", 2);
                result.put("msg", "密码错误");
                ObjectMapper objectMapper = new ObjectMapper();
                resultJson = objectMapper.writeValueAsString(result);
            } catch (IOException e1) {
                LOGGER.error("validate password fail getWriter:", e1);
            }
            printWriter.append(resultJson);
            return null;
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
                                            Authentication auth) throws IOException {
        LOGGER.debug("发放凭证...");
        JwtUserVo user = (JwtUserVo) auth.getPrincipal();

        JwtConfig jwtConfig = jwtTokenUtil.getJwtConfig();

        String token = jwtTokenUtil.create(user);
        LOGGER.debug("add response header jwt token, key:{}, value:{}{}", jwtConfig.getHeaderKey(), jwtConfig.getHeaderPrefix(), token);
        res.addHeader(jwtConfig.getHeaderKey(), jwtConfig.getHeaderPrefix() + token);
        res.setCharacterEncoding("UTF-8");
        res.setContentType("application/json; charset=utf-8");
        Map<String, Object> tokenResult = new HashMap<>();
        tokenResult.put(jwtConfig.getHeaderKey(), jwtConfig.getHeaderPrefix() + token);
        PrintWriter printWriter = res.getWriter();
        Map<String, Object> result = new HashMap<>();
        result.put("code", 1);
        result.put("msg", "成功");
        result.put("data", tokenResult);
        ObjectMapper objectMapper = new ObjectMapper();
        printWriter.append(objectMapper.writeValueAsString(result));
    }
}
